interface SetType<T> {
    items: Array<T>;

    add(element: T): boolean;

    delete(element: T): boolean;

    has(element: T): boolean;

    clear(): void;

    size(): number;

    values(): T[];

    union(otherSet: SetType<T>): SetType<T>; //并集
    intersection(otherSet: SetType<T>): SetType<T>; //交集
    difference(otherSet: SetType<T>): SetType<T>; // 差集
    isSubsetOf(otherSet: SetType<T>): boolean; // 是否为子级
}

// set数据结构：
// 书中是以object形式来写的， 但是object是有限制的， 不可以使用除了Symbol，string，number以外的来作为key，所以这里我决定使用Array来实现set
export default class Set_My<T extends Object> implements SetType<T> {
    items: Array<T>;

    constructor() {
        this.items = [];
    }

    add(element: T): boolean {
        if (!this.has(element)) {
            this.items.push(element);
            return true
        }
        console.warn(`The element "${element}" is repeated`)
        return false;
    }

    clear(): void {
        this.items = [];
    }

    delete(element: T): boolean {
        if (this.has(element)) {
            this.items.splice(this.items.indexOf(element), 1)
        }
        return false;
    }

    has(element: T): boolean {
        return !(this.items.indexOf(element) < 0);
    }

    size(): number {
        return this.items.length;
    }

    values(): T[] {
        return this.items;
    }

    // 并集
    union(otherSet: SetType<T>): SetType<T> {
        const newSet = new Set_My<T>();
        let arr = [...this.values(), ...otherSet.values()]
        for (let i = 0, len = arr.length; i < len; i++) {
            newSet.add(arr[i]);
        }
        return newSet;
    }


    // 交集
    intersection(otherSet: SetType<T>): SetType<T> {
        const newSet = new Set_My<T>();
        let thisSize = this.size();
        let otherSize = otherSet.size();
        let len: number,
            loopArr: Array<T>,
            equalsObj: SetType<T>;
        if (thisSize > otherSize) {
            len = otherSize;
            loopArr = otherSet.values();
            equalsObj = this;
        } else {
            len = thisSize;
            loopArr = this.values();
            equalsObj = otherSet;
        }
        for (let i = 0; i < len; i++) {
            if (equalsObj.has(loopArr[i])) {
                newSet.add(loopArr[i]);
            }
        }

        return newSet;
    }

    // 差集
    difference(otherSet: SetType<T>): SetType<T> {
        let newSet = new Set_My<T>();
        let loopArr = this.values();
        let len = loopArr.length;
        // 采用交集的方式来处理
        /*
        let intersectionSet = this.intersection(otherSet)
        for (let i = 0; i < len; i++) {
            if(intersectionSet.has(loopArr[i])){
                continue;
            }
            newSet.add(loopArr[i]);
        }
        */

        // 直接循环来处理
        // 注意 此处不能以优化交集的方式来处理 因为 this和otherSet的差集可能会不同
        for (let i = 0; i < len; i++) {
            if (otherSet.has(loopArr[i])) {
                continue;
            }
            newSet.add(loopArr[i])
        }
        return newSet;
    }

    // 当前集合是否为传入集合的子集
    isSubsetOf(otherSet: SetType<T>): boolean {
        if(otherSet.size()<this.size()){
            return false;
        }
        let loopArr = this.values();
        let len = this.size();
        for (let i = 0; i < len; i++) {
            if(otherSet.has(loopArr[i])){
                continue;
            }
            return false
        }

        return true
    }

}

const set = new Set_My<number>();
set.add(1);
console.log(set.values());
console.log(set.has(1));
console.log(set.size());

set.add(2);
console.log(set.values());
console.log(set.has(2));
console.log(set.size());

set.add(1);
console.log(set.values());
console.log(set.has(1));
console.log(set.size());

set.delete(1);
console.log(set.values());
console.log(set.has(1));
console.log(set.size());

set.delete(2);
console.log(set.values());
console.log(set.has(2));
console.log(set.size());
